home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / rip2 / iface.c < prev    next >
C/C++ Source or Header  |  1993-08-16  |  20KB  |  787 lines

  1. /* IP interface control and configuration routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by PA0GRI 
  5.  */
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "proc.h"
  9. #include "iface.h"
  10. #include "ip.h"
  11. #include "netuser.h"
  12. #include "ax25.h"
  13. #include "enet.h"
  14. #include "arp.h"
  15. #include "pktdrvr.h"
  16. #include "cmdparse.h"
  17. #include "commands.h"
  18. #include "nr4.h"
  19. #include "socket.h"
  20. #include "mailbox.h" 
  21.  
  22. #ifdef NETROM
  23. extern struct iface *Nr_iface;
  24. extern char Nralias[];
  25. #endif
  26.  
  27. static void showiface __ARGS((struct iface *ifp));
  28. int mask2width __ARGS((int32 mask));
  29. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  30. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  31. static int ifbbscall __ARGS((int argc,char *argv[],void *p));
  32. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  33. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  34. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  35. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  36. static int ifforw __ARGS((int argc,char *argv[],void *p));
  37. static int ifencap __ARGS((int argc,char *argv[],void *p));
  38. static int ifdescr __ARGS((int argc,char *argv[],void *p));
  39. static int ifpaclen __ARGS((int argc,char *argv[],void *p));
  40. static int ifbctext __ARGS((int argc,char *argv[],void *p));
  41. static int ifcdigi __ARGS((int argc,char *argv[],void *p));
  42.  
  43. /* Interface list header */
  44. struct iface *Ifaces = &Loopback;
  45.  
  46. /* Loopback pseudo-interface */
  47. struct iface Loopback = {
  48. #ifdef ENCAP
  49.     &Encap,     /* Link to next entry */
  50. #else
  51.     NULLIF,
  52. #endif
  53.     "loopback", /* name     */
  54.     NULLCHAR,   /* description */
  55.     0x7f000001L,    /* addr         127.0.0.1 */
  56.     0xffffffffL,    /* broadcast    255.255.255.255 */
  57.     0xffffffffL,    /* netmask      255.255.255.255 */
  58.     MAXINT16,       /* mtu          No limit */
  59. #ifdef AX25
  60.     0,          /* AX.25 paclen, if applicable */
  61. #endif
  62.     0,      /* flags    */
  63. #ifdef NETROM
  64.     0,      /* quality  */
  65. #endif
  66.     0,              /* trace        */
  67.     NULLCHAR,       /* trfile       */
  68.     NULLFILE,       /* trfp         */
  69.     NULLIF,         /* forw         */
  70.     NULLPROC,       /* rxproc       */
  71.     NULLPROC,       /* txproc       */
  72.     NULLPROC,       /* supv         */
  73.     0,              /* dev          */
  74.     NULL,           /* (*ioctl)     */
  75.     NULLFP,         /* (*iostatus)  */
  76.     NULLFP,         /* (*stop)      */
  77.     NULLCHAR,       /* hwaddr       */
  78. #ifdef AX25
  79.     NULLCHAR,       /* digi         */
  80. #ifdef MAILBOX
  81.     NULLCHAR,       /* bbscall      */
  82. #endif
  83.     NULLCHAR,       /* bctext       */
  84. #endif /* AX25 */
  85.     NULL,           /* extension    */
  86.     CL_NONE,        /* type         */
  87.     0,              /* xdev         */
  88.     0,              /* port         */
  89.     &Iftypes[0],    /* iftype       */
  90.     NULLFP,         /* (*send)      */
  91.     NULLFP,         /* (*output)    */
  92.     NULLFP,         /* (*raw)       */
  93.     NULLVFP,        /* (*show)      */
  94.     NULLFP,         /* (*discard)   */
  95.     NULLFP,         /* (*echo)      */
  96.     0,              /* ipsndcnt     */
  97.     0,              /* rawsndcnt    */
  98.     0,              /* iprecvcnt    */
  99.     0,              /* rawrcvcnt    */
  100.     0,              /* lastsent     */
  101.     0,              /* lastrecv     */
  102. };
  103.  
  104. #ifdef ENCAP
  105. /* Encapsulation pseudo-interface */
  106. struct iface Encap = {
  107.     NULLIF,
  108.     "encap",        /* name         */
  109.     NULLCHAR,   /* description */
  110.     INADDR_ANY,     /* addr         0.0.0.0 */
  111.     0xffffffffL,    /* broadcast    255.255.255.255 */
  112.     0xffffffffL,    /* netmask      255.255.255.255 */
  113.     MAXINT16,       /* mtu          No limit */
  114. #ifdef AX25
  115.     0,          /* AX.25 paclen, if applicable */
  116. #endif
  117.     0,      /* flags    */
  118. #ifdef NETROM
  119.     0,      /* quality  */
  120. #endif
  121.     0,              /* trace        */
  122.     NULLCHAR,       /* trfile       */
  123.     NULLFILE,       /* trfp         */
  124.     NULLIF,         /* forw         */
  125.     NULLPROC,       /* rxproc       */
  126.     NULLPROC,       /* txproc       */
  127.     NULLPROC,       /* supv         */
  128.     0,              /* dev          */
  129.     NULL,           /* (*ioctl)     */
  130.     NULLFP,         /* (*iostatus)  */
  131.     NULLFP,         /* (*stop)      */
  132.     NULLCHAR,       /* hwaddr       */
  133. #ifdef AX25
  134.     NULLCHAR,       /* digi         */
  135. #ifdef MAILBOX
  136.     NULLCHAR,       /* bbscall      */
  137. #endif
  138.     NULLCHAR,       /* bctext       */
  139. #endif
  140.     NULL,           /* extension    */
  141.     CL_NONE,        /* type         */
  142.     0,              /* xdev         */
  143.     0,              /* port         */
  144.     &Iftypes[0],    /* iftype       */
  145.     ip_encap,       /* (*send)      */
  146.     NULLFP,         /* (*output)    */
  147.     NULLFP,         /* (*raw)       */
  148.     NULLVFP,        /* (*show)      */
  149.     NULLFP,         /* (*discard)   */
  150.     NULLFP,         /* (*echo)      */
  151.     0,              /* ipsndcnt     */
  152.     0,              /* rawsndcnt    */
  153.     0,              /* iprecvcnt    */
  154.     0,              /* rawrcvcnt    */
  155.     0,              /* lastsent     */
  156.     0,              /* lastrecv     */
  157. };
  158. #endif /*ENCAP*/
  159.  
  160. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  161.  
  162. struct cmds DFAR Ifcmds[] = {
  163. #ifdef AX25
  164. #ifdef MAILBOX
  165.     "bbscall",              ifbbscall,      0,      2,      NULLCHAR,
  166. #endif
  167.     "bctext",               ifbctext,       0,      2,      NULLCHAR,
  168. #endif
  169.     "broadcast",            ifbroad,        0,      2,      NULLCHAR,
  170.     "description",          ifdescr,        0,      0,      NULLCHAR,
  171. #ifdef AX25
  172.     "cdigi",                ifcdigi,        0,      2,      NULLCHAR,
  173. #endif
  174.     "encapsulation",        ifencap,        0,      2,      NULLCHAR,
  175.     "forward",              ifforw,         0,      2,      NULLCHAR,
  176.     "ipaddress",            ifipaddr,       0,      2,      NULLCHAR,
  177.     "linkaddress",          iflinkadr,      0,      2,      NULLCHAR,
  178.     "mtu",                  ifmtu,          0,      2,      NULLCHAR,
  179.     "netmask",              ifnetmsk,       0,      2,      NULLCHAR,
  180. #ifdef AX25
  181.     "paclen",       ifpaclen,   0,  2,  NULLCHAR,
  182. #endif
  183.     "rxbuf",        ifrxbuf,    0,  2,  NULLCHAR,
  184.     NULLCHAR,
  185. };
  186.  
  187. /* Set interface parameters */
  188. int
  189. doifconfig(argc,argv,p)
  190. int argc;
  191. char *argv[];
  192. void *p;
  193. {
  194.     struct iface *ifp;
  195.     int i;
  196.  
  197.     if(argc < 2){
  198.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  199.             showiface(ifp);
  200.         return 0;
  201.     }
  202.     if((ifp = if_lookup(argv[1])) == NULLIF){
  203.     tprintf(Badinterface,argv[1]);
  204.         return 1;
  205.     }
  206.     if(argc == 2){
  207.         showiface(ifp);
  208.         if ( ifp->show != NULLVFP ) {
  209.             (*ifp->show)(ifp);
  210.         }
  211.         return 0;
  212.     }
  213.     if(argc == 3){
  214.         tputs("Argument missing\n");
  215.         return 1;
  216.     }
  217.     for(i=2;i<argc-1;i+=2)
  218.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  219.  
  220.     return 0;
  221. }
  222.  
  223. /* Set interface IP address */
  224. static int
  225. ifipaddr(argc,argv,p)
  226. int argc;
  227. char *argv[];
  228. void *p;
  229. {
  230.     struct iface *ifp = p;
  231.  
  232.     /* Do not allow loopback iface to be changed ! - WG7J */
  233.     if(ifp == &Loopback) {
  234.     tputs("Cannot change IP address !\n");
  235.     return 0;
  236.     }
  237.     ifp->addr = resolve(argv[1]);
  238.     return 0;
  239. }
  240.  
  241.  
  242. /* Set link (hardware) address */
  243. static int
  244. iflinkadr(argc,argv,p)
  245. int argc;
  246. char *argv[];
  247. void *p;
  248. {
  249.     struct iface *ifp = p;
  250.  
  251.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  252.         tputs("Can't set link address\n");
  253.         return 1;
  254.     }
  255.     if(ifp->hwaddr != NULLCHAR)
  256.         free(ifp->hwaddr);
  257.     ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  258.     (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  259. #ifdef MAILBOX
  260. #ifdef NETROM
  261.     if(ifp == Nr_iface) /*the netrom call just got changed! - WG7J*/
  262.         setmbnrid();
  263. #endif
  264. #endif
  265.     return 0;
  266. }
  267.  
  268. #ifdef AX25
  269. #ifdef MAILBOX
  270.  
  271. /* Set bbs ax.25 address */
  272. static int
  273. ifbbscall(argc,argv,p)
  274. int argc;
  275. char *argv[];
  276. void *p;
  277. {
  278.     struct iface *ifp = p;
  279.  
  280.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL ||
  281.        ifp->type != CL_AX25){
  282.         tputs("Can't set bbs call\n");
  283.         return 1;
  284.     }
  285.     if(ifp->bbscall == NULLCHAR)
  286.         ifp->bbscall = mallocw(AXALEN);
  287.     setcall(ifp->bbscall,argv[1]);
  288.     return 0;
  289. }
  290. #endif /* MAILBOX */
  291.  
  292. /* Set cross band digi call address */
  293. static int
  294. ifcdigi(argc,argv,p)
  295. int argc;
  296. char *argv[];
  297. void *p;
  298. {
  299.     struct iface *ifp = p;
  300.  
  301.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL ||
  302.        ifp->type != CL_AX25){
  303.         tputs("Can't set cdigi call\n");
  304.         return 1;
  305.     }
  306.     if(ifp->cdigi == NULLCHAR)
  307.         ifp->cdigi = mallocw(AXALEN);
  308.     setcall(ifp->cdigi,argv[1]);
  309.     return 0;
  310. }
  311.  
  312. /* Set ax.25 bctext */
  313. static int
  314. ifbctext(argc,argv,p)
  315. int argc;
  316. char *argv[];
  317. void *p;
  318. {
  319.     struct iface *ifp = p;
  320.  
  321.     if(ifp->type != CL_AX25){
  322.         tprintf("%s: not an ax.25 port!\n",ifp->name);
  323.         return 1;
  324.     }
  325.     if(ifp->bctext != NULLCHAR)
  326.         free(ifp->bctext);
  327.     if(strlen(argv[1]) == 0) {  /* clearing the buffer */
  328.         ifp->bctext = NULL;
  329.         return 0;
  330.     }
  331.     ifp->bctext = strdup(argv[1]);
  332.     return 0;
  333. }
  334. #endif /* AX25 */
  335.  
  336. /* Set interface broadcast address. This is actually done
  337.  * by installing a private entry in the routing table.
  338.  */
  339. static int
  340. ifbroad(argc,argv,p)
  341. int argc;
  342. char *argv[];
  343. void *p;
  344. {
  345.     struct iface *ifp = p;
  346.     struct route *rp;
  347.  
  348.     rp = rt_blookup(ifp->broadcast,32);
  349.     if(rp != NULLROUTE && rp->iface == ifp)
  350.         rt_drop(ifp->broadcast,32);
  351.     ifp->broadcast = resolve(argv[1]);
  352.     rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  353.     return 0;
  354. }
  355.  
  356. /* Set the network mask. This is actually done by installing
  357.  * a routing entry.
  358.  */
  359. static int
  360. ifnetmsk(argc,argv,p)
  361. int argc;
  362. char *argv[];
  363. void *p;
  364. {
  365.     struct iface *ifp = p;
  366.     struct route *rp;
  367.  
  368.     /* Remove old entry if it exists */
  369.     rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  370.     if(rp != NULLROUTE)
  371.         rt_drop(rp->target,rp->bits);
  372.  
  373.     ifp->netmask = htol(argv[1]);
  374.     rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  375.     return 0;
  376. }
  377.  
  378. /* Command to set interface encapsulation mode */
  379. static int
  380. ifencap(argc,argv,p)
  381. int argc;
  382. char *argv[];
  383. void *p;
  384. {
  385.     struct iface *ifp = p;
  386.  
  387.     if(setencap(ifp,argv[1]) != 0){
  388.         tprintf("Encapsulation mode '%s' unknown\n",argv[1]);
  389.         return 1;
  390.     }
  391.     return 0;
  392. }
  393. /* Function to set encapsulation mode */
  394. int
  395. setencap(ifp,mode)
  396. struct iface *ifp;
  397. char *mode;
  398. {
  399.     struct iftype *ift;
  400.  
  401.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  402.         if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  403.             break;
  404.     if(ift->name == NULLCHAR){
  405.         return -1;
  406.     }
  407.     ifp->iftype = ift;
  408.     ifp->send = ift->send;
  409.     ifp->output = ift->output;
  410.     ifp->type = ift->type;
  411. #ifdef AX25
  412.     if(ift->type == CL_AX25) {
  413.         extern char *axbctext;
  414.  
  415. #ifdef MAILBOX
  416.         if(!ifp->bbscall) {
  417.             ifp->bbscall = mallocw(AXALEN);
  418.             memcpy(ifp->bbscall,Bbscall,AXALEN);
  419.         }
  420. #endif
  421.         if(!ifp->bctext && axbctext)    /* Set the beacon id */
  422.             ifp->bctext = strdup(axbctext);
  423.         ifp->paclen = Paclen; /* default to the 'ax25 paclen' value */
  424.         ifp->flags += AX25_BEACON+MAIL_BEACON+AX25_DIGI+LOG_AXHEARD+LOG_IPHEARD;
  425.     }
  426. #endif
  427.     return 0;
  428. }
  429.  
  430. /* Set interface receive buffer size */
  431. static int
  432. ifrxbuf(argc,argv,p)
  433. int argc;
  434. char *argv[];
  435. void *p;
  436. {
  437.     return 0;       /* To be written */
  438. }
  439.  
  440. /* Set interface Maximum Transmission Unit */
  441. static int
  442. ifmtu(argc,argv,p)
  443. int argc;
  444. char *argv[];
  445. void *p;
  446. {
  447.     struct iface *ifp = p;
  448.  
  449.     ifp->mtu = atoi(argv[1]);
  450. #ifdef NETROM
  451.     /* Make sure NETROM mtu <= 236 ! - WG7J */
  452.     if(ifp == Nr_iface)
  453.         if(Nr_iface->mtu > NR4MAXINFO)
  454.             Nr_iface->mtu = NR4MAXINFO;
  455. #endif
  456.     return 0;
  457. }
  458.  
  459. #ifdef AX25
  460.  
  461. /* Set interface AX.25 Paclen, and adjust the NETROM mtu for the
  462.  * smallest paclen. - WG7J
  463.  */
  464. static int
  465. ifpaclen(argc,argv,p)
  466. int argc;
  467. char *argv[];
  468. void *p;
  469. {
  470.     struct iface *ifp = p;
  471. #ifdef NETROM
  472.     int tmp;
  473. #endif
  474.  
  475.     if(ifp->iftype->type == CL_AX25) {
  476.     ifp->paclen = atoi(argv[1]);
  477. #ifdef NETROM
  478.     if(ifp->flags & IS_NR_IFACE)
  479.         if((tmp=ifp->paclen - 20) < Nr_iface->mtu)
  480.         Nr_iface->mtu = tmp;
  481. #endif
  482.     } else
  483.     tputs("Not ax.25 interface!\n");
  484.     return 0;
  485. }
  486. #endif
  487.  
  488. /* Set interface forwarding */
  489. static int
  490. ifforw(argc,argv,p)
  491. int argc;
  492. char *argv[];
  493. void *p;
  494. {
  495.     struct iface *ifp = p;
  496.  
  497.     ifp->forw = if_lookup(argv[1]);
  498.     if(ifp->forw == ifp)
  499.         ifp->forw = NULLIF;
  500.     return 0;
  501. }
  502.  
  503. /*give a little description for each interface - WG7J*/
  504. static int
  505. ifdescr(argc,argv,p)
  506. int argc;
  507. char *argv[];
  508. void *p;
  509. {
  510.     struct iface *ifp = p;
  511.  
  512. #ifdef NETROM
  513. #ifdef ENCAP
  514.     if((ifp == &Loopback) || (ifp == &Encap) || (ifp == Nr_iface))
  515. #else
  516.     if((ifp == &Loopback) || (ifp == Nr_iface))
  517. #endif /*ENCAP*/
  518. #else  /*NETROM*/
  519. #ifdef ENCAP
  520.     if((ifp == &Loopback) || (ifp == &Encap))
  521. #else
  522.     if(ifp == &Loopback)
  523. #endif /*ENCAP*/
  524. #endif /*NETROM*/
  525.         return 0;
  526.  
  527.     if(ifp->descr != NULLCHAR){
  528.         free(ifp->descr);
  529.         ifp->descr = NULLCHAR;        /* reset the pointer */
  530.     }
  531.     if(!strlen(argv[1]))
  532.         return 0;           /* clearing the buffer */
  533.  
  534.     ifp->descr = mallocw(strlen(argv[1])+5); /* allow for the EOL char etc */
  535.     strcpy(ifp->descr, argv[1]);
  536.     strcat(ifp->descr, "\n");         /* add the EOL char */
  537.  
  538.     return 0;
  539. }
  540.  
  541. /* Display the parameters for a specified interface */
  542. static void
  543. showiface(ifp)
  544. register struct iface *ifp;
  545. {
  546.     char tmp[25];
  547.  
  548.     tprintf("%-8s IP addr %s MTU %u Link encap ",ifp->name,
  549.      inet_ntoa(ifp->addr),(int)ifp->mtu);
  550.     if(ifp->iftype == NULLIFT){
  551.         tputs("not set\n");
  552.     } else {
  553.         tprintf("%s\n",ifp->iftype->name);
  554.         if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR) {
  555.             tprintf("         Link addr %s",
  556.                 (*ifp->iftype->format)(tmp,ifp->hwaddr));
  557. #ifdef AX25
  558.             if(ifp->iftype->type == CL_AX25) {
  559. #ifdef MAILBOX
  560.                 tprintf("   BBS %s",pax25(tmp,ifp->bbscall));
  561. #endif
  562.                 if(ifp->cdigi)
  563.                     tprintf("   Cdigi %s",pax25(tmp,ifp->cdigi));
  564.                 tprintf("   Paclen %d\n",(int)ifp->paclen);
  565.                 if(ifp->bctext)
  566.                     tprintf("         BCText: %s\n",ifp->bctext);
  567.             }
  568. #endif
  569. #ifdef NETROM
  570.               else if(ifp == Nr_iface) {
  571.                 tprintf("   Alias %s\n",Nralias);
  572.             }
  573. #endif
  574. #if((defined AX25) || (defined NETROM))
  575.             else
  576. #endif
  577.                 tputc('\n');
  578.         }
  579.     }
  580.     tprintf("         flags 0x%lx trace 0x%x netmask 0x%08lx broadcast %s\n",
  581.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  582.     if(ifp->forw != NULLIF)
  583.         tprintf("         output forward to %s\n",ifp->forw->name);
  584.     tprintf("         sent: ip %lu tot %lu idle %s\n",
  585.      ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  586.     tprintf("         recv: ip %lu tot %lu idle %s\n",
  587.      ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  588.     if(ifp->descr != NULLCHAR)
  589.     tprintf("         descr: %s",ifp->descr);
  590.  
  591. }
  592.  
  593. /* Command to detach an interface */
  594. int
  595. dodetach(argc,argv,p)
  596. int argc;
  597. char *argv[];
  598. void *p;
  599. {
  600.     register struct iface *ifp;
  601.  
  602.     if((ifp = if_lookup(argv[1])) == NULLIF){
  603.     tprintf(Badinterface,argv[1]);
  604.         return 1;
  605.     }
  606.     if(if_detach(ifp) == -1)
  607.         tputs("Can't detach loopback or encap interface\n");
  608.     return 0;
  609. }
  610. /* Detach a specified interface */
  611. int
  612. if_detach(ifp)
  613. register struct iface *ifp;
  614. {
  615.     struct iface *iftmp;
  616.     struct route *rp,*rptmp;
  617.     int i,j;
  618.     struct ax_route *axr, *axr1;
  619.     struct arp_tab *ap, *ap1;
  620.  
  621. #ifdef ENCAP
  622.     if(ifp == &Loopback || ifp == &Encap)
  623. #else
  624.     if(ifp == &Loopback)
  625. #endif
  626.         return -1;
  627.  
  628. #ifdef AX25
  629.     /* Drop all ax25 routes that points to this interface */
  630.     for(axr = Ax_routes; axr != NULLAXR; axr = axr1) {
  631.         axr1 = axr->next;/* Save the next pointer */
  632.         if(axr->iface == ifp)
  633.             ax_drop(axr->target, ifp);
  634.         /* axr will be undefined after ax_drop() */
  635.     }
  636. #endif
  637.  
  638.     /* Drop all ARP's that point to this interface */
  639.     for(i = 0; i < HASHMOD; ++i)
  640.         for(ap = Arp_tab[i]; ap != NULLARP; ap = ap1) {
  641.         ap1 = ap->next;    /* Save the next pointer */
  642.         if(ap->iface == ifp)
  643.             arp_drop(ap);
  644.         /* ap will be undefined after arp_drop() */
  645.         }
  646.  
  647.  
  648.     /* Drop all routes that point to this interface */
  649.     if(R_default.iface == ifp)
  650.         rt_drop(0L,0);  /* Drop default route */
  651.  
  652.     for(i=0;i<HASHMOD;i++){
  653.         for(j=0;j<32;j++){
  654.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  655.                 /* Save next pointer in case we delete this entry */
  656.                 rptmp = rp->next;
  657.                 if(rp->iface == ifp)
  658.                     rt_drop(rp->target,rp->bits);
  659.             }
  660.         }
  661.     }
  662.     /* Unforward any other interfaces forwarding to this one */
  663.     for(iftmp = Ifaces;iftmp != NULLIF;iftmp = iftmp->next){
  664.         if(iftmp->forw == ifp)
  665.             iftmp->forw = NULLIF;
  666.     }
  667.  
  668.     /* Call device shutdown routine, if any */
  669.     if(ifp->stop != NULLFP)
  670.         (*ifp->stop)(ifp);
  671.  
  672.     killproc(ifp->rxproc);
  673.     killproc(ifp->txproc);
  674.     killproc(ifp->supv);
  675.  
  676. #ifdef NETROM
  677.     /*make sure that the netrom interface is properly detached
  678.      *fixed 11/15/91, Johan. K. Reinalda, WG7J/PA3DIS
  679.      */
  680.     if(strcmp(ifp->name,"netrom") == 0) {
  681.     for(iftmp=Ifaces;iftmp;iftmp=iftmp->next)
  682.         iftmp->flags &= ~IS_NR_IFACE; /* this 'resets' active interfaces */
  683.     Nr_iface = NULLIF;
  684.     }
  685. #endif
  686.  
  687.     /* Free allocated memory associated with this interface */
  688.     free(ifp->name);
  689.     free(ifp->hwaddr);
  690. #ifdef AX25
  691. #ifdef MAILBOX
  692.     free(ifp->bbscall);
  693. #endif
  694.     free(ifp->cdigi);
  695.     free(ifp->bctext);
  696. #endif
  697.     free(ifp->descr);
  698.  
  699.     /* Remove from interface list */
  700.     if(ifp == Ifaces){
  701.         Ifaces = ifp->next;
  702.     } else {
  703.         /* Search for entry just before this one
  704.          * (necessary because list is only singly-linked.)
  705.          */
  706.         for(iftmp = Ifaces;iftmp != NULLIF ;iftmp = iftmp->next)
  707.             if(iftmp->next == ifp)
  708.                 break;
  709.         if(iftmp != NULLIF && iftmp->next == ifp)
  710.             iftmp->next = ifp->next;
  711.     }
  712.     /* Finally free the structure itself */
  713.     free((char *)ifp);
  714.     return 0;
  715. }
  716.  
  717. /* Given the ascii name of an interface, return a pointer to the structure,
  718.  * or NULLIF if it doesn't exist
  719.  */
  720. struct iface *
  721. if_lookup(name)
  722. char *name;
  723. {
  724.     register struct iface *ifp;
  725.  
  726.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  727.         if(stricmp(ifp->name,name) == 0)
  728.             break;
  729.     return ifp;
  730. }
  731.  
  732. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  733.  * NULLIF otherwise.
  734.  * This is used to tell if an incoming IP datagram is for us, or if it
  735.  * has to be routed.
  736.  */
  737. struct iface *
  738. ismyaddr(addr)
  739. int32 addr;
  740. {
  741.     register struct iface *ifp;
  742.  
  743.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  744.         if(addr == ifp->addr)
  745.             break;
  746.     return ifp;
  747. }
  748.  
  749. /* Given a network mask, return the number of contiguous 1-bits starting
  750.  * from the most significant bit.
  751.  */
  752. int
  753. mask2width(mask)
  754. int32 mask;
  755. {
  756.     int width,i;
  757.  
  758.     width = 0;
  759.     for(i = 31;i >= 0;i--){
  760.         if(!(mask & (1L << i)))
  761.             break;
  762.         width++;
  763.     }
  764.     return width;
  765. }
  766.  
  767. /* return buffer with name + comment */
  768. char *
  769. if_name(ifp,comment)
  770. struct iface *ifp;
  771. char *comment;
  772. {
  773.     char *result = mallocw( strlen(ifp->name) + strlen(comment) + 1 );
  774.     strcpy( result, ifp->name );
  775.     return strcat( result, comment );
  776. }
  777.  
  778. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  779. int
  780. bitbucket(ifp,bp)
  781. struct iface *ifp;
  782. struct mbuf *bp;
  783. {
  784.     free_p(bp);
  785.     return 0;
  786. }
  787.